package com.yfp.group.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.math.Money;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.notify.WxPayPartnerNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.WxPayPartnerRefundNotifyV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayPartnerOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yfp.common.core.constant.CacheConstants;
import com.yfp.common.core.domain.R;
import com.yfp.common.core.domain.ResponseEnum;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.common.datascope.annotation.DataScope;
import com.yfp.common.redis.utils.RedisDelayQueueUtil;
import com.yfp.common.redis.utils.RedisNumber;
import com.yfp.common.security.utils.SecurityUtils;
import com.yfp.goods.api.RemoteComboService;
import com.yfp.goods.domain.Combo;
import com.yfp.goods.domain.ComboGroupDTO;
import com.yfp.group.config.EnterpriseOrderProperties;
import com.yfp.group.domain.*;
import com.yfp.group.domain.dto.*;
import com.yfp.group.domain.vo.*;
import com.yfp.group.enums.*;
import com.yfp.group.mapper.EnterpriseOrderClientMapper;
import com.yfp.group.mapper.EnterpriseOrderMapper;
import com.yfp.group.service.*;
import com.yfp.machine.api.RemoteMachineService;
import com.yfp.machine.domain.MachineDto;
import com.yfp.operation.api.RemoteOperationService;
import com.yfp.operation.domain.EnterpriseOrderDeliveryPlanDTO;
import com.yfp.operation.domain.EnterpriseOrderDetailDeliveryPlanDTO;
import com.yfp.operation.domain.OrderComboGroupDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【enterprise_order(企业订单)】的数据库操作Service实现
 * @createDate 2024-08-10 09:41:36
 */
@Service
@Slf4j
public class EnterpriseOrderServiceImpl extends ServiceImpl<EnterpriseOrderMapper, EnterpriseOrder> implements EnterpriseOrderService {

    @Resource
    private EnterpriseOrderMapper enterpriseOrderMapper;
    @Resource
    private EnterpriseOrderDetailsService enterpriseOrderDetailsService;
    @Resource
    private EnterpriseOrderClientService enterpriseOrderClientService;
    @Resource
    private EnterpriseService enterpriseService;
    @Resource
    private EnterpriseCapitalService enterpriseCapitalService;
    @Resource
    private RemoteComboService remoteComboService;
    @Resource
    private RemoteMachineService remoteMachineService;
    @Resource
    private RemoteOperationService remoteOperationService;
    @Resource
    private EnterpriseOrderClientMapper enterpriseOrderClientMapper;
    @Resource
    private PayService payService;
    @Resource
    private EnterpriseOrderProperties enterpriseOrderProperties;
    @Resource
    private RedisNumber redisNumber;
    @Resource
    private RedisDelayQueueUtil redisDelayQueueUtil;

    /**
     * 获取企业用户领取订单详情
     *
     * @param clientId
     * @return
     */
    @Override
    public List<ClientOrderVO> clientOrder(String clientId) {
        return enterpriseOrderMapper.clientOrder(clientId);
    }

    /**
     * 企业订单列表
     *
     * @param enterpriseOrderDTO
     * @return
     */
    @Override
    @DataScope(deptAlias = "m")
    public FirmOrderVO enterpriseOrderList(EnterpriseOrderDTO enterpriseOrderDTO) {
        FirmOrderVO firmOrderVO = new FirmOrderVO();
        // 设置分页参数
        PageHelper.startPage(enterpriseOrderDTO.getPageNum(), enterpriseOrderDTO.getPageSize());
        List<EnterpriseOrderVO> list = enterpriseOrderMapper.enterpriseOrderList(enterpriseOrderDTO);
        if (list.isEmpty()) {
            return firmOrderVO;
        }

        PageInfo<EnterpriseOrderVO> pageInfo = new PageInfo<>(list);
        List<EnterpriseOrderVO> vos = pageInfo.getList();
        long total = pageInfo.getTotal();
        firmOrderVO.setTotal(total);
        firmOrderVO.setList(vos);
        return firmOrderVO;
    }

    @Override
    public List<ComboGroupDTO> getGroupShelfComboList() {
        List<ComboGroupDTO> groupShelfComboList = remoteComboService.getGroupShelfComboList().getData();
        return groupShelfComboList;
    }

    @Override
    public String settleCombo(ComboSettleDTO comboSettleDTO) {
        // 检查是否存在待支付订单
        if (this.hasWaitPayOrder()) {
            throw new ServiceException(ResponseEnum.HAS_GROUP_ORDER.getMsg(), ResponseEnum.HAS_GROUP_ORDER.getCode());
        }
        // 创建订单信息
        return this.createOrder(comboSettleDTO);
    }

    @Override
    public Boolean hasWaitPayOrder() {
        Long userId = SecurityUtils.getUserId();
        Enterprise enterprise = enterpriseService.findByUserId(userId);
        Long count = enterpriseOrderMapper.countWaitPayOrderByEnterpriseId(enterprise.getId());
        return count > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createOrder(ComboSettleDTO comboSettleDTO) {
        Long userId = SecurityUtils.getUserId();
        // 校验传入数据
        List<String> comboIds = comboSettleDTO.getComboDTOS().stream().map(ComboDTO::getId).collect(Collectors.toList());
        Assert.notEmpty(comboIds, "购买套餐不能为空");
        R<List<Combo>> combosR = remoteComboService.getComboByIds(comboIds);
        Assert.isFalse(R.isError(combosR), combosR.getMsg());
        List<Combo> combos = combosR.getData().stream().filter(item -> NumberUtil.equals(1, Optional.ofNullable(item.getShelf()).orElse(0))).filter(item -> NumberUtil.equals(1, Optional.ofNullable(item.getGroupShelf()).orElse(0))).collect(Collectors.toList());
        Assert.notEmpty(combos, "无可购买套餐");
        Map<String, Combo> comboMapById = combos.stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));
        // 计算价格
        BigDecimal originalPrice = comboSettleDTO.getComboDTOS().stream().map(item -> {
            Combo combo = comboMapById.getOrDefault(item.getId(), null);
            Assert.notNull(combo, "套餐已下架");
            BigDecimal totalPrice = NumberUtil.mul(combo.getSalePrice(), item.getNum().toString());
            return totalPrice;
        }).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 组装创建订单数据
        Enterprise enterprise = enterpriseService.findByUserId(userId);
        EnterpriseOrder enterpriseOrder = new EnterpriseOrder();
        enterpriseOrder.setOrderSn(redisNumber.getORD());
        enterpriseOrder.setEnterpriseId(enterprise.getId());
        enterpriseOrder.setOriginalPrice(originalPrice);
        enterpriseOrder.setPayMoney(originalPrice);
        enterpriseOrder.setMachineId(enterprise.getMachineId());
        enterpriseOrder.setPayStatus(EnterpriseOrderPayStatusEnums.WAIT_PAY.getCode());
        enterpriseOrder.setCreateTime(DateUtil.date());
        enterpriseOrder.setStatus(EnterpriseOrderStatusEnums.UNAVAILABLE.getCode());
        enterpriseOrder.setSaleTime(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), 1)));

        // 组装创建订单详情数据
        List<EnterpriseOrderDetails> enterpriseOrderDetailsList = comboSettleDTO.getComboDTOS().stream().map(item -> {
            Combo combo = comboMapById.getOrDefault(item.getId(), new Combo());
            EnterpriseOrderDetails orderDetails = new EnterpriseOrderDetails();
            orderDetails.setEnterpriseOrderSn(enterpriseOrder.getOrderSn());
            orderDetails.setComboId(combo.getComboId());
            orderDetails.setComboPrice(new Money(combo.getSalePrice()).getAmount());
            orderDetails.setComboName(combo.getName());
            orderDetails.setComboNum(item.getNum());
            orderDetails.setComboSurplusNum(item.getNum());
            orderDetails.setPayMoney(NumberUtil.mul(new Money(combo.getSalePrice()).getAmount(), item.getNum()));
            return orderDetails;
        }).collect(Collectors.toList());

        // 创建企业资金流水
        EnterpriseCapital enterpriseCapital = new EnterpriseCapital();
        enterpriseCapital.setEnterpriseId(enterpriseOrder.getEnterpriseId());
        enterpriseCapital.setMoney(enterpriseOrder.getPayMoney());
        enterpriseCapital.setTransactionId(enterpriseOrder.getOrderSn());
        enterpriseCapitalService.createConsumeOrder(enterpriseCapital);

        // 创建订单插入数据
        this.baseMapper.insert(enterpriseOrder);
        enterpriseOrderDetailsService.saveBatch(enterpriseOrderDetailsList);

        // 将订单信息加入到延迟队列。如果超时30分钟没有支付就取消订单
        redisDelayQueueUtil.addDelayQueue(enterpriseOrder.getOrderSn(), 30, TimeUnit.MINUTES, CacheConstants.ENTERPRISE_ORDER_CREATE_DELAY_QUEUE_KEY);
        return enterpriseOrder.getOrderSn();
    }

    @Override
    public EnterpriseOrderQrCodeInfoVO orderQrCodeInfo() {
        Long userId = SecurityUtils.getUserId();
        // 获取用户信息
        Enterprise enterprise = enterpriseService.findByUserId(userId);

        DateTime saleTime = DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), 1));
        List<EnterpriseOrder> enterpriseOrders = this.selectAvailableByDateAndEnterpriseId(saleTime, enterprise.getId());
        EnterpriseOrder enterpriseOrder = CollUtil.getFirst(enterpriseOrders);
        if (Objects.isNull(enterpriseOrder)) {
            return null;
        }

        // 生成二维码
        EnterpriseOrderQrCodeInfoVO orderQrCodeInfoVO = this.generateQrCode(enterpriseOrder, enterprise);
        return orderQrCodeInfoVO;
    }

    @Override
    public EnterpriseOrderQrCodeInfoVO orderQrCodeInfoByOrderSn(String orderSn) {
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(orderSn);

        // 检测订单是否可用
        Boolean isAvailable = this.checkOrderAvailable(enterpriseOrder);
        if (!isAvailable) {
            throw new ServiceException("领餐二维码无效");
        }

        // 检测销售日期是否是 今天的订单、明天的订单
        Boolean isShow = this.checkQrCodeShowTime(enterpriseOrder.getSaleTime());
        if (!isShow) {
            throw new ServiceException("领餐二维码已过期");
        }
        Long userId = SecurityUtils.getUserId();
        // 获取用户信息
        Enterprise enterprise = enterpriseService.findByUserId(userId);
        // 生成二维码
        EnterpriseOrderQrCodeInfoVO orderQrCodeInfoVO = this.generateQrCode(enterpriseOrder, enterprise);
        return orderQrCodeInfoVO;
    }

    @Override
    public EnterpriseOrderQrCodeInfoVO generateQrCode(EnterpriseOrder enterpriseOrder, Enterprise enterprise) {
        // https://test-console-yfp.qafanle.com/openminiapp?orderSn=42590800733573&type=1
        HashMap<String, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("orderSn", enterpriseOrder.getOrderSn());
        objectObjectHashMap.put("type", enterprise.getType().toString());
        String params = HttpUtil.toParams(objectObjectHashMap);
        String qrCodeUrl = enterpriseOrderProperties.getBaseQrCodeUrl() + "?" + params;

        // 组装返回数据
        EnterpriseOrderQrCodeInfoVO orderQrCodeInfoVO = new EnterpriseOrderQrCodeInfoVO();
        orderQrCodeInfoVO.setQrCodeUrl(qrCodeUrl);
        orderQrCodeInfoVO.setOrderSn(enterpriseOrder.getOrderSn());
        orderQrCodeInfoVO.setSaleTime(enterpriseOrder.getSaleTime());
        orderQrCodeInfoVO.setEnterpriseName(enterprise.getEnterpriseName());

        return orderQrCodeInfoVO;
    }

    @Override
    public Boolean checkQrCodeShowTime(Date saleTime) {
        DateTime date = DateUtil.date();
        DateTime beginDate = DateUtil.beginOfDay(date);
        DateTime endDate = DateUtil.endOfDay(DateUtil.offsetDay(date, 1));
        boolean in = DateUtil.isIn(saleTime, beginDate, endDate);
        return in;
    }

    @Override
    public List<EnterpriseOrderListVO> orderList(Date startTime, Date endTime) {
        Long userId = SecurityUtils.getUserId();
        Enterprise enterprise = enterpriseService.findByUserId(userId);
        // 获取订单列表
        List<EnterpriseOrder> enterpriseOrders = enterpriseOrderMapper.selectByDateBetweenAndEnterpriseId(DateUtil.beginOfDay(startTime), DateUtil.endOfDay(endTime), enterprise.getId());
        // 获取订单详情
        List<String> orderSnList = enterpriseOrders.stream().map(EnterpriseOrder::getOrderSn).collect(Collectors.toList());
        List<EnterpriseOrderDetails> enterpriseOrderDetailsList = enterpriseOrderDetailsService.listByOrderSns(orderSnList);
        Map<String, List<EnterpriseOrderDetails>> detailListByOrderSn = enterpriseOrderDetailsList.stream().collect(Collectors.groupingBy(EnterpriseOrderDetails::getEnterpriseOrderSn));
        // 获取套餐信息
        List<String> comboIds = enterpriseOrderDetailsList.stream().map(EnterpriseOrderDetails::getComboId).distinct().collect(Collectors.toList());
        R<List<Combo>> combosR = remoteComboService.getComboByIds(comboIds);
        Assert.isFalse(R.isError(combosR), combosR.getMsg());
        Map<String, Combo> comboMapById = combosR.getData().stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));

        // 组装订单详情
        List<EnterpriseOrderListVO> orderListVOList = enterpriseOrders.stream().map(item -> {
            EnterpriseOrderListVO enterpriseOrderListVO = BeanUtil.toBean(item, EnterpriseOrderListVO.class);
            List<EnterpriseOrderDetails> detailsList = detailListByOrderSn.getOrDefault(item.getOrderSn(), new ArrayList<>());
            List<EnterpriseOrderDetailVO> detailVOList = BeanUtil.copyToList(detailsList, EnterpriseOrderDetailVO.class).stream().map(item2 -> {
                Combo combo = comboMapById.getOrDefault(item2.getComboId(), new Combo());
                // 设置套餐图片
                item2.setComboImgUrl(combo.getThumbUrl());
                return item2;
            }).collect(Collectors.toList());
            enterpriseOrderListVO.setEnterpriseOrderDetailVOS(detailVOList);
            enterpriseOrderListVO.setTotalComboNum(detailVOList.stream().mapToInt(EnterpriseOrderDetailVO::getComboNum).sum());
            // 二维码按钮是否展示
            if (this.checkOrderAvailable(item) && this.checkQrCodeShowTime(item.getSaleTime())) {
                enterpriseOrderListVO.setQrCodeShow(Boolean.TRUE);
            } else {
                enterpriseOrderListVO.setQrCodeShow(Boolean.FALSE);
            }
            return enterpriseOrderListVO;
        }).sorted(Comparator.comparing(EnterpriseOrderListVO::getCreateTime).reversed()).collect(Collectors.toList());

        return orderListVOList;
    }

    @Override
    public void orderCancel(String orderSn) {
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(orderSn);
        // 待支付状态才能取消订单
        if (!EnterpriseOrderPayStatusEnums.WAIT_PAY.getCode().equals(enterpriseOrder.getPayStatus())) {
            return;
        }
        // 如果订单是微信支付，或微信二维码支付
        if (PayTypeEnums.WECHAT.getCode().equals(enterpriseOrder.getPayWay()) || PayTypeEnums.WECHAT_QRCODE.getCode().equals(enterpriseOrder.getPayWay())) {
            // 获取用户信息
            Enterprise enterprise = enterpriseService.selectById(enterpriseOrder.getEnterpriseId());
            // 获取微信支付商户号
            String subMchId = payService.getSubMchIdByMachineId(enterprise.getMachineId());
            String outTradeNo = payService.orderSnToOutTradeNo(enterpriseOrder.getOrderSn(), PayTypeEnums.getByCode(enterpriseOrder.getPayWay()));
            payService.closeOrder(outTradeNo, subMchId);
        }

        enterpriseOrder.setPayStatus(EnterpriseOrderPayStatusEnums.CANCELED.getCode());
        enterpriseOrder.setStatus(EnterpriseOrderStatusEnums.UNAVAILABLE.getCode());
        enterpriseOrder.setCancelTime(DateUtil.date());
        enterpriseOrderMapper.updateByOrderSn(enterpriseOrder);
    }

    @Override
    public EnterpriseOrderInfoVO orderInfo(String orderSn) {
        // 获取订单信息
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(orderSn);
        List<EnterpriseOrderDetails> enterpriseOrderDetails = enterpriseOrderDetailsService.listByOrderSns(Arrays.asList(orderSn));

        List<String> comboIds = enterpriseOrderDetails.stream().map(EnterpriseOrderDetails::getComboId).collect(Collectors.toList());
        R<List<Combo>> combosR = remoteComboService.getComboByIds(comboIds);
        Assert.isFalse(R.isError(combosR), combosR.getMsg());
        Map<String, Combo> comboMapById = combosR.getData().stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));

        // 组装订单详情
        EnterpriseOrderInfoVO enterpriseOrderInfoVO = BeanUtil.toBean(enterpriseOrder, EnterpriseOrderInfoVO.class);
        List<EnterpriseOrderDetailVO> detailVOList = BeanUtil.copyToList(enterpriseOrderDetails, EnterpriseOrderDetailVO.class).stream().map(item -> {
            // 计算套餐总价
            item.setTotalPrice(NumberUtil.mul(new Money(item.getComboPrice()).getAmount(), item.getComboNum()));
            Combo combo = comboMapById.getOrDefault(item.getComboId(), new Combo());
            // 设置套餐图片
            item.setComboImgUrl(combo.getThumbUrl());
            return item;
        }).collect(Collectors.toList());
        enterpriseOrderInfoVO.setEnterpriseOrderDetailVOS(detailVOList);

        return enterpriseOrderInfoVO;
    }


    @Override
    public EnterpriseOrderPayInfoVO orderPaymentInfo(String orderSn) {
        Long userId = SecurityUtils.getUserId();

        // 获取订单信息
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(orderSn);
        List<EnterpriseOrderDetails> enterpriseOrderDetails = enterpriseOrderDetailsService.listByOrderSns(Arrays.asList(orderSn));
        // 获取用户信息
        Enterprise enterprise = enterpriseService.findByUserId(userId);
        // 获取设备信息
        String machineId = enterprise.getMachineId();
        R<MachineDto> machineDtoR = remoteMachineService.selectOne(machineId);
        Assert.isFalse(R.isError(machineDtoR), machineDtoR.getMsg());
        MachineDto machineDto = machineDtoR.getData();
        List<String> comboIds = enterpriseOrderDetails.stream().map(EnterpriseOrderDetails::getComboId).collect(Collectors.toList());
        R<List<Combo>> combosR = remoteComboService.getComboByIds(comboIds);
        Assert.isFalse(R.isError(combosR), combosR.getMsg());
        Map<String, Combo> comboMapById = combosR.getData().stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));

        // 组装订单详情
        EnterpriseOrderPayInfoVO enterpriseOrderPayInfoVO = BeanUtil.toBean(enterpriseOrder, EnterpriseOrderPayInfoVO.class);
        List<EnterpriseOrderDetailVO> detailVOList = BeanUtil.copyToList(enterpriseOrderDetails, EnterpriseOrderDetailVO.class).stream().map(item -> {
            // 计算套餐总价
            item.setTotalPrice(NumberUtil.mul(new Money(item.getComboPrice()).getAmount(), item.getComboNum()));
            Combo combo = comboMapById.getOrDefault(item.getComboId(), new Combo());
            // 设置套餐图片
            item.setComboImgUrl(combo.getThumbUrl());
            return item;
        }).collect(Collectors.toList());
        enterpriseOrderPayInfoVO.setEnterpriseOrderDetailVOS(detailVOList);
        // 设置余额支付金额
        enterpriseOrderPayInfoVO.setPayBalance(enterprise.getBalance());
        // 设置设备信息
        enterpriseOrderPayInfoVO.setMachineName(machineDto.getMachineName());
        enterpriseOrderPayInfoVO.setMachineAddress(machineDto.getPositionAddr());
        return enterpriseOrderPayInfoVO;
    }

    @Override
    public List<SalesStatsComboVO> salesStatsCombo(Date date) {
        Long userId = SecurityUtils.getUserId();

        // 获取用户信息
        Enterprise enterprise = enterpriseService.findByUserId(userId);

        // 获取订单信息
        List<EnterpriseOrder> enterpriseOrders = this.selectAvailableByDateAndEnterpriseId(DateUtil.beginOfDay(date), enterprise.getId());
        List<EnterpriseOrderDetails> enterpriseOrderDetails = enterpriseOrderDetailsService.listByOrderSns(enterpriseOrders.stream().map(EnterpriseOrder::getOrderSn).collect(Collectors.toList()));

        List<String> comboIds = enterpriseOrderDetails.stream().map(EnterpriseOrderDetails::getComboId).collect(Collectors.toList());
        R<List<Combo>> combosR = remoteComboService.getComboByIds(comboIds);
        Assert.isFalse(R.isError(combosR), combosR.getMsg());
        Map<String, Combo> comboMapById = combosR.getData().stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));

        // 组装订单详情
        List<SalesStatsComboVO> salesStatsComboVOS = BeanUtil.copyToList(enterpriseOrderDetails, SalesStatsComboVO.class).stream().map(item -> {
            Combo combo = comboMapById.getOrDefault(item.getComboId(), new Combo());
            // 设置套餐图片
            item.setComboImgUrl(combo.getThumbUrl());
            return item;
        }).collect(Collectors.toList());

        return salesStatsComboVOS;
    }

    @Override
    public List<SalesStatsClientVO> salesStatsClient(SalesStatsClientDTO salesStatsClientDTO) {
        Long userId = SecurityUtils.getUserId();

        // 获取用户信息
        Enterprise enterprise = enterpriseService.findByUserId(userId);

        // 获取订单信息
        List<EnterpriseOrder> enterpriseOrders = this.selectAvailableByDateAndEnterpriseId(DateUtil.beginOfDay(salesStatsClientDTO.getDate()), enterprise.getId());
        List<String> orderSnList = enterpriseOrders.stream().map(EnterpriseOrder::getOrderSn).collect(Collectors.toList());
        if (CollUtil.isEmpty(orderSnList)) {
            return new ArrayList<>();
        }
        // 获取订单客户信息
        List<EnterpriseOrderClient> enterpriseOrderClients = enterpriseOrderClientService.listByOrderSnAndRoomNum(orderSnList, salesStatsClientDTO.getRoomNum());

        // 获取 orderCombo 订单的状态
        List<String> orderComboIds = enterpriseOrderClients.stream().map(EnterpriseOrderClient::getOrderComboId).collect(Collectors.toList());
        R<List<OrderComboGroupDTO>> groupOrderInfoR = remoteOperationService.listGroupOrderInfo(orderComboIds);
        Assert.isFalse(R.isError(groupOrderInfoR), groupOrderInfoR.getMsg());
        Map<String, OrderComboGroupDTO> orderComboMapById = groupOrderInfoR.getData().stream().collect(Collectors.toMap(OrderComboGroupDTO::getOrderId, Function.identity()));

        // 获取套餐名称
        List<String> comboIds = enterpriseOrderClients.stream().map(EnterpriseOrderClient::getComboId).collect(Collectors.toList());
        R<List<Combo>> combosR = remoteComboService.getComboByIds(comboIds);
        Assert.isFalse(R.isError(combosR), combosR.getMsg());
        Map<String, Combo> comboMapById = combosR.getData().stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));

        // 组装订单详情
        List<SalesStatsClientVO> salesStatsClientVOS = BeanUtil.copyToList(enterpriseOrderClients, SalesStatsClientVO.class).stream().map(item -> {
            // 设置套餐名称
            Combo combo = comboMapById.getOrDefault(item.getComboId(), new Combo());
            item.setComboName(combo.getName());
            // 设置订单状态
            OrderComboGroupDTO orderComboGroupDTO = orderComboMapById.getOrDefault(item.getOrderComboId(), new OrderComboGroupDTO());
            item.setStatus(orderComboGroupDTO.getStatus());
            return item;
        }).filter(item -> {
            if (Objects.nonNull(salesStatsClientDTO.getStatus()) && !NumberUtil.equals(0, salesStatsClientDTO.getStatus())) {
                return salesStatsClientDTO.getStatus().equals(item.getStatus());
            }
            return true;
        }).collect(Collectors.toList());

        // 相同订单id聚合数据
        salesStatsClientVOS = salesStatsClientVOS.stream().collect(Collectors.groupingBy(SalesStatsClientVO::getOrderComboId)).values().stream().map(item -> {
            String roomNumList = item.stream().map(SalesStatsClientVO::getRoomNum).distinct().collect(Collectors.joining(","));
            String comboIdList = item.stream().map(SalesStatsClientVO::getComboId).distinct().collect(Collectors.joining(","));
            String comboNameList = item.stream().map(SalesStatsClientVO::getComboName).distinct().collect(Collectors.joining(","));
            BigDecimal comboNum = item.stream().map(SalesStatsClientVO::getComboNum).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add);
            int status = item.stream().map(SalesStatsClientVO::getStatus).anyMatch(n -> n == 1) ? 1 : 2;
            String orderComboIdList = item.stream().map(SalesStatsClientVO::getOrderComboId).distinct().collect(Collectors.joining(","));

            SalesStatsClientVO salesStatsClientVO = new SalesStatsClientVO();
            salesStatsClientVO.setRoomNum(roomNumList);
            salesStatsClientVO.setComboId(comboIdList);
            salesStatsClientVO.setComboName(comboNameList);
            salesStatsClientVO.setComboNum(comboNum.intValue());
            salesStatsClientVO.setStatus(status);
            salesStatsClientVO.setOrderComboId(orderComboIdList);
            return salesStatsClientVO;
        }).sorted(Comparator.comparing(SalesStatsClientVO::getRoomNum)).collect(Collectors.toList());

        return salesStatsClientVOS;
    }

    /**
     * 套餐数据汇总
     *
     * @param enterpriseOrderDTO
     * @return
     */
    @Override
    public List<ComboVO> comboCollect(EnterpriseOrderDTO enterpriseOrderDTO) {
        List<ComboVO> comboVOS = enterpriseOrderMapper.comboCollect(enterpriseOrderDTO);
        return comboVOS;
    }

    /**
     * 订单详情列表
     *
     * @param enterpriseOrderClientDTO
     * @return
     */
    @Override
    public List<EnterpriseOrderClientVO> orderDetail(EnterpriseOrderClientDTO enterpriseOrderClientDTO) {
        List<EnterpriseOrderClientVO> list = enterpriseOrderClientMapper.orderDetail(enterpriseOrderClientDTO);
        return list;
    }

    /**
     * 订单详情列表数据补全
     * @param list
     * @return
     */
    @Override
    public List<EnterpriseOrderClientVO> orderDetailComplement(List<EnterpriseOrderClientVO> list) {
        if (!list.isEmpty()) {
            HashMap<String, EnterpriseOrderClientVO> map = new HashMap<>();
            for (EnterpriseOrderClientVO enterpriseOrderClientVO : list) {
                String orderComboId = enterpriseOrderClientVO.getOrderComboId();
                if (map.containsKey(orderComboId)) {
                    EnterpriseOrderClientVO orderVO = map.get(orderComboId);
                    orderVO.setComboName(orderVO.getComboName() + "、" + enterpriseOrderClientVO.getComboName());
                    orderVO.setComboNum(orderVO.getComboNum() + enterpriseOrderClientVO.getComboNum());
                    orderVO.setComboPrice(orderVO.getComboPrice().add(enterpriseOrderClientVO.getComboPrice().multiply(new BigDecimal(enterpriseOrderClientVO.getComboNum()))));
                } else {
                    enterpriseOrderClientVO.setComboNum(enterpriseOrderClientVO.getComboNum());
                    enterpriseOrderClientVO.setComboName(enterpriseOrderClientVO.getComboName());
                    enterpriseOrderClientVO.setComboPrice(enterpriseOrderClientVO.getComboPrice().multiply(new BigDecimal(enterpriseOrderClientVO.getComboNum())));
                    map.put(orderComboId, enterpriseOrderClientVO);
                }
            }

            List<EnterpriseOrderClientVO> clientVOList = new ArrayList<>(map.values()).stream().sorted(Comparator.comparing(EnterpriseOrderClientVO::getRemark)).collect(Collectors.toList());
            return clientVOList;
        }

        return list;
    }

    /**
     * 修改取餐完成时间
     * @param enterpriseOrderSn
     */
    @Override
    @Transactional
    public void updateFinishTime(String enterpriseOrderSn) {

        log.info("修改取餐完成时间参数:{}",enterpriseOrderSn);

        // 获取套餐数量
        Integer comboNum = enterpriseOrderDetailsService.getComboNum(enterpriseOrderSn);
        // 该企业订单关联的已完成订单的套餐数量
        Integer num = enterpriseOrderClientService.getOrderComboIds(enterpriseOrderSn);

        log.info("获取套餐数量:{}",comboNum);
        log.info("该企业订单关联的已完成订单的套餐数量:{}",num);

        if (comboNum == num) {
            enterpriseOrderMapper.updateFinishTime(enterpriseOrderSn);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object orderPaymentWx(String orderSn, Integer payType, String openId) {
        Long userId = SecurityUtils.getUserId();
        DateTime dateTime = DateUtil.date();
        // 获取用户信息
        Enterprise enterprise = enterpriseService.findByUserId(userId);
        // 获取订单信息
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(orderSn);
        // 获取微信支付商户号
        String subMchId = payService.getSubMchIdByMachineId(enterprise.getMachineId());
        // 创建微信支付订单
        CreateWxPayOrderDTO createWxPayOrderDTO = new CreateWxPayOrderDTO();
        createWxPayOrderDTO.setDescription("购买团餐");
        createWxPayOrderDTO.setTimeExpire(dateTime.offset(DateField.MINUTE, 30));
        createWxPayOrderDTO.setTotalPrice(enterpriseOrder.getPayMoney());
        createWxPayOrderDTO.setSubMchId(subMchId);
        createWxPayOrderDTO.setAttach(WxPayAttach.ORDER_BUY_COMBO.getCode());
        if (PayTypeEnums.WECHAT.getCode().equals(payType)) {
            createWxPayOrderDTO.setOpenid(openId);
            // 调用微信支付
            createWxPayOrderDTO.setOutTradeNo(payService.orderSnToOutTradeNo(orderSn, PayTypeEnums.WECHAT));
            WxPayUnifiedOrderV3Result.JsapiResult wxJsapiPayOrder = payService.createWxJsapiPayOrder(createWxPayOrderDTO);
            String wxPrepayId = StrUtil.replace(wxJsapiPayOrder.getPackageValue(), "prepay_id=", "");

            EnterpriseOrder enterpriseOrder1 = new EnterpriseOrder();
            enterpriseOrder1.setOrderSn(orderSn);
            enterpriseOrder1.setPayWay(PayTypeEnums.WECHAT.getCode());
            enterpriseOrder1.setPrepayId(wxPrepayId);
            enterpriseOrderMapper.updateByOrderSn(enterpriseOrder1);
            EnterpriseCapital enterpriseCapital = new EnterpriseCapital();
            // enterpriseCapital.setEnterpriseId(enterpriseOrder.getEnterpriseId());
            enterpriseCapital.setType(3);
            enterpriseCapital.setPrepayId(wxPrepayId);
            // enterpriseCapital.setMoney(enterpriseOrder.getPayMoney());
            enterpriseCapital.setBalance(enterprise.getBalance());
            enterpriseCapital.setTransactionId(orderSn);
            enterpriseCapitalService.updateByTransactionId(enterpriseCapital);
            return wxJsapiPayOrder;
        } else if (PayTypeEnums.WECHAT_QRCODE.getCode().equals(payType)) {
            // 调用微信二维码支付
            createWxPayOrderDTO.setOutTradeNo(payService.orderSnToOutTradeNo(orderSn, PayTypeEnums.WECHAT_QRCODE));
            String codeUrl = payService.createWxNativePayOrder(createWxPayOrderDTO);
            EnterpriseOrder enterpriseOrder1 = new EnterpriseOrder();
            enterpriseOrder1.setOrderSn(orderSn);
            enterpriseOrder1.setPayWay(PayTypeEnums.WECHAT_QRCODE.getCode());
            enterpriseOrderMapper.updateByOrderSn(enterpriseOrder1);
            EnterpriseCapital enterpriseCapital = new EnterpriseCapital();
            // enterpriseCapital.setEnterpriseId(enterpriseOrder.getEnterpriseId());
            enterpriseCapital.setType(4);
            // enterpriseCapital.setMoney(enterpriseOrder.getPayMoney());
            enterpriseCapital.setBalance(enterprise.getBalance());
            enterpriseCapital.setTransactionId(orderSn);
            enterpriseCapitalService.updateByTransactionId(enterpriseCapital);
            return codeUrl;
        } else {
            throw new ServiceException("支付类型错误");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderPaymentBalance(String orderSn, Integer payType) {
        Long userId = SecurityUtils.getUserId();
        DateTime dateTime = DateUtil.date();
        // 获取用户信息
        Enterprise enterprise = enterpriseService.findByUserId(userId);
        // 获取订单信息
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(orderSn);

        // 校验余额是否足够
        if (NumberUtil.isLess(enterprise.getBalance(), enterpriseOrder.getPayMoney())) {
            throw new ServiceException("余额不足");
        }

        // 创建余额支付订单
        CreateWxPayOrderDTO createWxPayOrderDTO = new CreateWxPayOrderDTO();
        createWxPayOrderDTO.setDescription("购买团餐");
        createWxPayOrderDTO.setOutTradeNo(orderSn);
        createWxPayOrderDTO.setTimeExpire(dateTime.offset(DateField.MINUTE, 30));
        createWxPayOrderDTO.setTotalPrice(enterpriseOrder.getPayMoney());
        createWxPayOrderDTO.setOpenid(enterprise.getOpenId());
        createWxPayOrderDTO.setAttach(WxPayAttach.ORDER_BUY_COMBO.getCode());
        if (PayTypeEnums.BALANCE.getCode().equals(payType)) {
            // 调用余额支付
            EnterpriseOrder enterpriseOrder1 = new EnterpriseOrder();
            enterpriseOrder1.setOrderSn(orderSn);
            enterpriseOrder1.setPayWay(PayTypeEnums.BALANCE.getCode());
            enterpriseOrderMapper.updateByOrderSn(enterpriseOrder1);
            EnterpriseCapital enterpriseCapital = new EnterpriseCapital();
            // enterpriseCapital.setEnterpriseId(enterpriseOrder.getEnterpriseId());
            enterpriseCapital.setType(6);
            enterpriseCapital.setMoney(enterpriseOrder.getPayMoney());
            enterpriseCapital.setTransactionId(orderSn);
            enterpriseCapitalService.updateByTransactionId(enterpriseCapital);
            payService.createBalancePayOrder(createWxPayOrderDTO);
        } else {
            throw new ServiceException("支付类型错误");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void parseOrderNotifyResult(WxPayPartnerNotifyV3Result.DecryptNotifyResult result) {
        // 获取订单编号
        String orderSn = payService.outTradeNoToOrderSn(result.getOutTradeNo());

        EnterpriseOrder enterpriseOrder1 = enterpriseOrderMapper.selectByOrderSn(orderSn);
        if (EnterpriseOrderPayStatusEnums.PAID.getCode().equals(enterpriseOrder1.getPayStatus())) {
            return;
        }

        // 更新订单状态
        EnterpriseOrder enterpriseOrder = new EnterpriseOrder();
        enterpriseOrder.setOrderSn(orderSn);
        enterpriseOrder.setPayStatus(EnterpriseOrderPayStatusEnums.PAID.getCode());
        enterpriseOrder.setPayTime(DateUtil.parse(result.getSuccessTime()));
        enterpriseOrder.setPayTradeNo(result.getTransactionId());
        enterpriseOrder.setStatus(EnterpriseOrderStatusEnums.AVAILABLE.getCode());
        enterpriseOrderMapper.updateByOrderSn(enterpriseOrder);
        // 更新订单状态
        EnterpriseCapital enterpriseCapital = new EnterpriseCapital();
        enterpriseCapital.setTransactionId(orderSn);
        enterpriseCapital.setPayTime(DateUtil.parse(result.getSuccessTime()));
        enterpriseCapital.setStatus(EnterpriseCapitalPayStatusEnums.PAID.getCode());
        enterpriseCapitalService.updateByTransactionId(enterpriseCapital);
        // 已支付订单移除延迟队列
        redisDelayQueueUtil.removeDelayedQueue(orderSn, CacheConstants.ENTERPRISE_ORDER_CREATE_DELAY_QUEUE_KEY);
        // 根据企业订单生成投放计划
        this.generateDeliveryPlan(orderSn);
    }

    @Override
    public void parseRefundNotifyResult(WxPayPartnerRefundNotifyV3Result.DecryptNotifyResult result) {

    }

    @Override
    public EnterpriseOrder getOrderStatus(String orderSn) {
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(orderSn);
        // 如果订单已支付，直接返回订单已支付
        if (EnterpriseOrderPayStatusEnums.PAID.getCode().equals(enterpriseOrder.getPayStatus())) {
            // 订单已支付
            return enterpriseOrder;
        }
        // 如果订单是微信支付，或微信二维码支付
        if (PayTypeEnums.WECHAT.getCode().equals(enterpriseOrder.getPayWay()) || PayTypeEnums.WECHAT_QRCODE.getCode().equals(enterpriseOrder.getPayWay())) {
            // 获取微信支付商户号
            Enterprise enterprise = enterpriseService.selectById(enterpriseOrder.getEnterpriseId());
            String subMchId = payService.getSubMchIdByMachineId(enterprise.getMachineId());
            // 微信订单编号
            String outTradeNo = payService.orderSnToOutTradeNo(orderSn, PayTypeEnums.getByCode(enterpriseOrder.getPayWay()));
            // 调用微信支付查询订单状态
            WxPayPartnerOrderQueryV3Result orderStatus = payService.getOrderStatus(outTradeNo, subMchId);
            if (WxPayConstants.WxpayTradeStatus.SUCCESS.equals(orderStatus.getTradeState())) {
                // 更新订单状态
                WxPayPartnerNotifyV3Result.DecryptNotifyResult decryptNotifyResult = BeanUtil.toBean(orderStatus, WxPayPartnerNotifyV3Result.DecryptNotifyResult.class);
                this.parseOrderNotifyResult(decryptNotifyResult);
                enterpriseOrder.setPayStatus(EnterpriseOrderPayStatusEnums.PAID.getCode());
                return enterpriseOrder;
            }
            return enterpriseOrder;
        }
        return enterpriseOrder;
    }

    /**
     * 订单管理列表导出
     *
     * @param enterpriseOrderDTO
     * @return
     */
    @Override
    @DataScope(deptAlias = "m")
    public List<EnterpriseOrderVO> deriveEnterpriseOrder(EnterpriseOrderDTO enterpriseOrderDTO) {
        List<EnterpriseOrderVO> list = enterpriseOrderMapper.enterpriseOrderList(enterpriseOrderDTO);
        return list;
    }

    @Override
    public void generateDeliveryPlan(String outTradeNo) {
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.selectByOrderSn(outTradeNo);
        List<EnterpriseOrderDetails> enterpriseOrderDetails = enterpriseOrderDetailsService.listByOrderSns(Arrays.asList(outTradeNo));
        Enterprise enterprise = enterpriseService.selectById(enterpriseOrder.getEnterpriseId());

        EnterpriseOrderDeliveryPlanDTO orderDeliveryPlanDTO = BeanUtil.toBean(enterpriseOrder, EnterpriseOrderDeliveryPlanDTO.class);
        List<EnterpriseOrderDetailDeliveryPlanDTO> detailDeliveryPlanDTOS = BeanUtil.copyToList(enterpriseOrderDetails, EnterpriseOrderDetailDeliveryPlanDTO.class);
        orderDeliveryPlanDTO.setEnterpriseOrderDetails(detailDeliveryPlanDTOS);
        orderDeliveryPlanDTO.setEnterpriseName(enterprise.getEnterpriseName());
        remoteOperationService.autoEnterprisePlacementPlan(orderDeliveryPlanDTO);
    }

    @Override
    public List<EnterpriseOrder> selectAvailableByDateAndEnterpriseId(DateTime saleTime, Long enterpriseId) {
        List<EnterpriseOrder> enterpriseOrders = enterpriseOrderMapper.selectByDateAndEnterpriseId(saleTime, enterpriseId).stream().filter(item -> this.checkOrderAvailable(item)).collect(Collectors.toList());
        return enterpriseOrders;
    }

    @Override
    public Boolean checkOrderAvailable(EnterpriseOrder enterpriseOrder) {
        // （状态:PAID(2, "已支付")、状态：AVAILABLE(1, "可用")）
        if (EnterpriseOrderPayStatusEnums.PAID.getCode().equals(enterpriseOrder.getPayStatus()) && EnterpriseOrderStatusEnums.AVAILABLE.getCode().equals(enterpriseOrder.getStatus())) {
            // 订单已支付，且订单可用
            return true;
        }
        return false;
    }
}




